Skip to content

Wrap up replacing Projectables with ExpressiveFor with synthesized properties#40

Merged
koenbeuk merged 7 commits intomainfrom
feat/expressive-for-synthesize
Apr 27, 2026
Merged

Wrap up replacing Projectables with ExpressiveFor with synthesized properties#40
koenbeuk merged 7 commits intomainfrom
feat/expressive-for-synthesize

Conversation

@koenbeuk
Copy link
Copy Markdown
Collaborator

@koenbeuk koenbeuk commented Apr 20, 2026

closes #37

Copilot AI review requested due to automatic review settings April 20, 2026 01:22
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR completes the migration away from [Expressive(Projectable = true)] by introducing/standardizing on [ExpressiveFor(..., Synthesize = true)], updating generators, tests, and documentation accordingly.

Changes:

  • Add generator support for ExpressiveForAttribute.Synthesize and emit synthesized, settable properties via a new SynthesizedPropertyEmitter.
  • Remove Projectable-specific generator logic, diagnostics, code fixers, tests, and documentation.
  • Update EF Core + MongoDB integration tests and docs to validate/describe synthesized-property behavior and mapping ignores.

Reviewed changes

Copilot reviewed 39 out of 39 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tests/ExpressiveSharp.Tests/Services/ExpressiveResolverTests.cs Updates resolver tests to validate synthesized-property registry keying and formula-only bodies.
tests/ExpressiveSharp.MongoDB.IntegrationTests/Tests/SynthesizedMongoIgnoreTests.cs Renames/rewrites Mongo integration tests to use synthesized properties and verify BSON ignore behavior.
tests/ExpressiveSharp.IntegrationTests/Tests/SynthesizedExpressiveTests.cs Updates provider-agnostic integration tests to cover synthesized-property runtime and expansion semantics.
tests/ExpressiveSharp.Generator.Tests/ExpressiveGenerator/ProjectableTests.cs Removes Projectable generator snapshot/diagnostic tests.
tests/ExpressiveSharp.Generator.Tests/ExpressiveGenerator/ProjectableTests.SimpleProjectableProperty_ManualBackingField.verified.txt Removes Projectable snapshot output.
tests/ExpressiveSharp.Generator.Tests/ExpressiveGenerator/ProjectableTests.ProjectableWithSetAccessor.verified.txt Removes Projectable snapshot output.
tests/ExpressiveSharp.Generator.Tests/ExpressiveGenerator/ProjectableTests.NullableValueTypeProperty_Ternary_FieldKeyword.verified.txt Removes Projectable snapshot output.
tests/ExpressiveSharp.Generator.Tests/ExpressiveGenerator/ProjectableTests.NonNullableValueTypeProperty_Ternary_ManualBackingField.verified.txt Removes Projectable snapshot output.
tests/ExpressiveSharp.Generator.Tests/ExpressiveGenerator/ProjectableTests.NonNullableValueTypeProperty_Ternary_FieldKeyword.verified.txt Removes Projectable snapshot output.
tests/ExpressiveSharp.Generator.Tests/ExpressiveGenerator/ExpressiveForTests.cs Adds new synthesize snapshot + diagnostic tests (EXP0031–EXP0033).
tests/ExpressiveSharp.Generator.Tests/ExpressiveGenerator/ExpressiveForTests.Synthesize_ReferenceTypeTarget_EmitsCoalesceForm.verified.txt Updates/extends snapshots to include synthesized partial output.
tests/ExpressiveSharp.Generator.Tests/ExpressiveGenerator/ExpressiveForTests.Synthesize_NullableValueTypeTarget_EmitsTernaryForm.verified.txt Updates snapshot for nullable value-type synthesize output.
tests/ExpressiveSharp.Generator.Tests/ExpressiveGenerator/ExpressiveForTests.Synthesize_NullableReferenceTypeTarget_EmitsTernaryForm.verified.txt Adds snapshot for nullable reference-type synthesize output.
tests/ExpressiveSharp.Generator.Tests/ExpressiveGenerator/ExpressiveForTests.Synthesize_NonNullableValueTypeTarget_EmitsCoalesceForm.verified.txt Adds snapshot for non-nullable value-type synthesize output.
tests/ExpressiveSharp.Generator.Tests/CodeFixers/ConvertProjectableToTernaryCodeFixProviderTests.cs Removes tests for the retired Projectable-to-ternary code fix.
tests/ExpressiveSharp.EntityFrameworkCore.IntegrationTests/Tests/Sqlite/SynthesizedExpressiveSqlTests.cs Updates EF Core SQLite integration tests to validate synthesized-property ignore + SQL rewriting.
src/ExpressiveSharp.MongoDB/Infrastructure/ExpressiveMongoIgnoreConvention.cs Updates convention docs to include synthesized properties as ignored/unmapped.
src/ExpressiveSharp.Generator/Models/SynthesizedPropertySpec.cs Introduces model for synthesized property emission parameters.
src/ExpressiveSharp.Generator/Models/ExpressiveForAttributeData.cs Parses Synthesize named argument for [ExpressiveFor].
src/ExpressiveSharp.Generator/Models/ExpressiveDescriptor.cs Adds SynthesisSpec to carry emission instructions to the generator.
src/ExpressiveSharp.Generator/Models/ExpressiveAttributeData.cs Removes now-retired Projectable flag parsing.
src/ExpressiveSharp.Generator/Interpretation/ProjectablePatternRecognizer.cs Removes Projectable pattern recognition implementation.
src/ExpressiveSharp.Generator/Interpretation/ExpressiveInterpreter.cs Removes Projectable-specific dispatch path.
src/ExpressiveSharp.Generator/Interpretation/ExpressiveInterpreter.BodyProcessors.cs Removes Projectable body processing pipeline.
src/ExpressiveSharp.Generator/Interpretation/ExpressiveForInterpreter.cs Adds synthesize resolution path, creates synthesis spec, and adds EXP0031–EXP0033 behavior.
src/ExpressiveSharp.Generator/Infrastructure/Diagnostics.cs Retires EXP0021–EXP0030 and introduces EXP0031–EXP0033 diagnostics.
src/ExpressiveSharp.Generator/ExpressiveGenerator.cs Emits synthesized property partial alongside expression factory output; adjusts registry entry kind for synthesize.
src/ExpressiveSharp.Generator/Emitter/SynthesizedPropertyEmitter.cs New emitter generating the synthesized property, backing fields, and (ternary/coalesce) accessors.
src/ExpressiveSharp.CodeFixers/ConvertProjectableToTernaryCodeFixProvider.cs Removes Projectable code fix provider.
src/ExpressiveSharp.Abstractions/Mapping/ExpressiveForAttribute.cs Adds Synthesize property to public attribute API.
src/ExpressiveSharp.Abstractions/ExpressiveAttribute.cs Removes Projectable property from [Expressive].
docs/reference/projectable-properties.md Removes the Projectable Properties reference page.
docs/reference/expressive-for.md Documents Synthesize = true behavior, requirements, and new diagnostics.
docs/reference/expressive-attribute.md Removes Projectable docs from [Expressive] reference.
docs/reference/diagnostics.md Removes Projectable diagnostic docs and adds EXP0031–EXP0033 docs and guidance.
docs/recipes/projection-middleware.md Updates guidance to use synthesized properties instead of Projectable properties.
docs/guide/migration-from-projectables.md Updates migration guidance to recommend synthesize or plain [ExpressiveFor].
docs/guide/integrations/mongodb.md Updates Mongo integration docs to reference synthesized properties rather than Projectables.
docs/.vitepress/config.mts Removes Projectable Properties page from sidebar.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +166 to +175
// EXP0032: the containing class must be partial so we can emit the synthesized property
// into a generated file.
if (!IsPartialType(targetType))
{
context.ReportDiagnostic(Diagnostic.Create(
Diagnostics.ExpressiveForSynthesizeRequiresPartial,
stubIdentifierLocation,
targetType.ToDisplayString(SymbolDisplayFormat.CSharpShortErrorMessageFormat)));
return null;
}
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Synthesize = true can currently target interface types (see GetTypeKeyword returning "interface"), but the synthesized member always emits backing fields, which are illegal in interfaces and will break compilation. Consider rejecting targetType.TypeKind == TypeKind.Interface (and possibly other non-field-capable containers) with a dedicated diagnostic before emitting the synthesis spec.

Copilot uses AI. Check for mistakes.
Comment on lines +190 to +212
// The stub must be a parameterless same-type member (property or method) so the
// synthesized property can delegate to it with no arguments. For non-property stubs
// we still accept zero-param instance methods.
ITypeSymbol stubReturnType;
bool stubIsProperty;
switch (stubSymbol)
{
case IPropertySymbol propSym when propSym.Parameters.Length == 0 && !propSym.IsStatic:
stubReturnType = propSym.Type;
stubIsProperty = true;
break;
case IMethodSymbol methodSym when methodSym.Parameters.Length == 0 && !methodSym.IsStatic:
stubReturnType = methodSym.ReturnType;
stubIsProperty = false;
break;
default:
context.ReportDiagnostic(Diagnostic.Create(
Diagnostics.ExpressiveForMemberNotFound,
stubIdentifierLocation,
memberName,
targetType.ToDisplayString(SymbolDisplayFormat.CSharpShortErrorMessageFormat)));
return null;
}
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the default case, ResolveSynthesize reports EXP0015 (target member not found) when the stub itself is invalid for synthesis (e.g., static, has parameters, wrong kind). That error message is misleading because the target member is intentionally absent when synthesizing. Recommend adding a specific diagnostic for “synthesize stub must be a parameterless instance property/method on the containing type” (or reusing a more appropriate existing one) so users get actionable feedback.

Copilot uses AI. Check for mistakes.
Comment on lines +100 to +103
"_" + char.ToLowerInvariant(propertyName[0]) + propertyName.Substring(1);

private static string MakeHasValueFlagName(string propertyName) =>
"_" + char.ToLowerInvariant(propertyName[0]) + propertyName.Substring(1) + "HasValue";
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The synthesized backing field/flag names are derived directly from the target property name (e.g. _fullName, _fullNameHasValue) without any collision check. If the user type already declares these members (common when migrating from manual/projectable patterns), the generator will emit uncompilable code. Consider generating a reserved/prefixed name (e.g. __expressive_fullName) and/or doing a symbol-based uniqueness check (like the old code fix did) and carrying the chosen names in SynthesizedPropertySpec.

Suggested change
"_" + char.ToLowerInvariant(propertyName[0]) + propertyName.Substring(1);
private static string MakeHasValueFlagName(string propertyName) =>
"_" + char.ToLowerInvariant(propertyName[0]) + propertyName.Substring(1) + "HasValue";
"__expressive_" + char.ToLowerInvariant(propertyName[0]) + propertyName.Substring(1);
private static string MakeHasValueFlagName(string propertyName) =>
"__expressive_" + char.ToLowerInvariant(propertyName[0]) + propertyName.Substring(1) + "HasValue";

Copilot uses AI. Check for mistakes.
Comment thread src/ExpressiveSharp.Generator/Emitter/SynthesizedPropertyEmitter.cs Outdated
Comment thread docs/guide/migration-from-projectables.md

// Attach the synthesis spec so the generator emits the partial property.
var useTernary = IsNullablePropertyType(stubReturnType);
var propertyTypeFqn = stubReturnType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stubReturnType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) drops nullable reference annotations, so synthesized properties for string? stubs get emitted as non-nullable string (and backing fields likewise). This can produce incorrect public API and nullable warnings/errors (esp. with warnings-as-errors). Use a SymbolDisplayFormat that includes ? (e.g. IncludeNullableReferenceTypeModifier) or derive the emitted type string from the stub syntax/nullability-aware display options so PropertyTypeFqn/BackingFieldTypeFqn preserve NRT annotations.

Suggested change
var propertyTypeFqn = stubReturnType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
var fullyQualifiedNullableFormat = SymbolDisplayFormat.FullyQualifiedFormat.WithMiscellaneousOptions(
SymbolDisplayFormat.FullyQualifiedFormat.MiscellaneousOptions |
SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier);
var propertyTypeFqn = stubReturnType.ToDisplayString(fullyQualifiedNullableFormat);

Copilot uses AI. Check for mistakes.
…roperties

A dedicated attribute that declares a settable property on a partial type
using an instance expression-bodied stub as the formula source. Replaces
the need for a flag on [ExpressiveFor] and gives the feature a clear,
intent-named entry point alongside [Expressive] and [ExpressiveFor].

Rules enforced by EXP0031-EXP0035:
- stub must be an expression-bodied property (EXP0033)
- stub must be an instance member (EXP0034)
- containing type must be declared partial (EXP0032)
- target name must not exist on the type (EXP0031, suggests [ExpressiveFor])
- target name must not shadow an inherited member (EXP0035)

Generator picks coalesce shape for non-nullable targets and ternary+flag
for nullable targets so materialized null stays distinguishable from
"not materialized". Synthesized properties are always public with an init
accessor.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment on lines +20 to +28
if (attribute.ConstructorArguments.Length == 1 &&
attribute.ConstructorArguments[0].Value is string name)
{
TargetName = name;
}
else
{
TargetName = null;
}
Comment on lines +30 to +43
foreach (var namedArgument in attribute.NamedArguments)
{
if (namedArgument.Key == "Transformers" && namedArgument.Value.Kind == TypedConstantKind.Array)
{
foreach (var element in namedArgument.Value.Values)
{
if (element.Value is INamedTypeSymbol typeSymbol)
{
transformerTypeNames.Add(
typeSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat));
}
}
}
}
Comment on lines +34 to +41
foreach (var element in namedArgument.Value.Values)
{
if (element.Value is INamedTypeSymbol typeSymbol)
{
transformerTypeNames.Add(
typeSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat));
}
}
…ping stubs

The MissingExpressiveAnalyzer warned when a member referenced in an expressive
context looked like it could benefit from [Expressive], even though a sibling
stub on the same type already registered an expression for it via either
[ExpressiveProperty("X")] or [ExpressiveFor(nameof(X))] / the two-arg
self-targeting form. The reference resolves to a member with an expandable
body but no direct [Expressive] attribute, so the heuristic fired.

Teaches the analyzer to check the containing type for a sibling whose mapping
attribute names the referenced member as its target, and treat it as
effectively expressive.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment on lines +270 to +292
foreach (var sibling in containingType.GetMembers())
{
if (SymbolEqualityComparer.Default.Equals(sibling, symbol))
continue;

foreach (var attr in sibling.GetAttributes())
{
if (attr.AttributeClass is not { } attrClass) continue;
var ns = attrClass.ContainingNamespace?.ToDisplayString();
if (ns != "ExpressiveSharp.Mapping") continue;

if (attrClass.Name == "ExpressivePropertyAttribute"
&& ExtractStringArg(attr, 0) == targetName)
{
return true;
}

if (attrClass.Name == "ExpressiveForAttribute" && MapsExpressiveForTo(attr, containingType, targetName))
{
return true;
}
}
}
Comment on lines +275 to +291
foreach (var attr in sibling.GetAttributes())
{
if (attr.AttributeClass is not { } attrClass) continue;
var ns = attrClass.ContainingNamespace?.ToDisplayString();
if (ns != "ExpressiveSharp.Mapping") continue;

if (attrClass.Name == "ExpressivePropertyAttribute"
&& ExtractStringArg(attr, 0) == targetName)
{
return true;
}

if (attrClass.Name == "ExpressiveForAttribute" && MapsExpressiveForTo(attr, containingType, targetName))
{
return true;
}
}
Comment on lines +623 to +626
foreach (var child in op.ChildOperations)
{
if (ContainsInvalidOperation(child)) return true;
}
Comment on lines +271 to +278
foreach (var reference in type.DeclaringSyntaxReferences)
{
if (reference.GetSyntax() is TypeDeclarationSyntax typeDecl
&& typeDecl.Modifiers.Any(SyntaxKind.PartialKeyword))
{
return true;
}
}
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark 'ExpressiveSharp Benchmarks'.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 1.50.

Benchmark suite Current: 6d62c4c Previous: cc0c346 Ratio
ExpressiveSharp.Benchmarks.ExpressionReplacerBenchmarks.Replace_Property 5200.84310798645 ns (± 1698.001373361245) 2934.442163194929 ns (± 19.529064598469024) 1.77
ExpressiveSharp.Benchmarks.TransformerBenchmarks.Transform_RemoveNullConditionalPatterns 560.3763828688654 ns (± 12.529835415588623) 169.6090742308518 ns (± 2.60408546443615) 3.30
ExpressiveSharp.Benchmarks.ExpressionResolverBenchmarks.Resolve_Method 19.132783565256332 ns (± 11.51342017220988) 10.05102585894721 ns (± 0.02119731370989029) 1.90
ExpressiveSharp.Benchmarks.TransformerBenchmarks.Transform_FlattenBlockExpressions 175.07942388852436 ns (± 21.772166404261082) 52.97142610788345 ns (± 0.019498051771350573) 3.31
ExpressiveSharp.Benchmarks.ExpressionResolverBenchmarks.Resolve_Constructor 30.125968544647613 ns (± 4.810837717316905) 8.16587499320507 ns (± 0.18200552110315804) 3.69
ExpressiveSharp.Benchmarks.ExpressionResolverBenchmarks.ResolveViaReflection_Property 31.254486336310705 ns (± 3.4176084890714407) 8.467363996165139 ns (± 0.021743345072564917) 3.69
ExpressiveSharp.Benchmarks.EFCoreQueryOverheadBenchmarks.ColdStart_Baseline 101491.52853190104 ns (± 25169.160244361097) 58751.30886314655 ns (± 595.9907548549759) 1.73
ExpressiveSharp.Benchmarks.ExpressionResolverBenchmarks.ResolveViaReflection_Method 34.45815195043882 ns (± 6.20204503967114) 10.036463543772697 ns (± 0.030056876603126764) 3.43
ExpressiveSharp.Benchmarks.PolyfillColdBuildWithNoiseBenchmarks.Cold(NoiseInvocationsPerFile: 0) 10581176.89732143 ns (± 4069600.7985521224) 4990743.776506697 ns (± 90936.16227381543) 2.12
ExpressiveSharp.Benchmarks.PolyfillColdBuildWithNoiseBenchmarks.Cold_E2E(NoiseInvocationsPerFile: 0) 11941020.812760416 ns (± 3397525.461013337) 4806456.70842634 ns (± 10147.276107721527) 2.48
ExpressiveSharp.Benchmarks.PolyfillSingleFileBenchmarks.Cold(CallSiteCount: 1) 208176.7574508102 ns (± 10370.260301928263) 104889.24656519397 ns (± 2868.715927167156) 1.98
ExpressiveSharp.Benchmarks.PolyfillSingleFileBenchmarks.Incremental_EditEntityFile(CallSiteCount: 1) 27827.077690633138 ns (± 3479.0945239355547) 11818.883805411202 ns (± 189.54186932935767) 2.35
ExpressiveSharp.Benchmarks.PolyfillSingleFileBenchmarks.Incremental_EditQueryFile(CallSiteCount: 1) 166066.9243727464 ns (± 1288.4402102501494) 101303.07506872107 ns (± 1229.255126150258) 1.64
ExpressiveSharp.Benchmarks.PolyfillSingleFileBenchmarks.Cold_E2E(CallSiteCount: 1) 181166.99744591347 ns (± 2490.7178375793196) 105710.69890485491 ns (± 383.11068384771824) 1.71
ExpressiveSharp.Benchmarks.PolyfillSingleFileBenchmarks.Incremental_EditEntityFile_E2E(CallSiteCount: 1) 23861.578878130233 ns (± 528.100781549043) 12263.877277119955 ns (± 54.566758713219706) 1.95
ExpressiveSharp.Benchmarks.PolyfillSingleFileBenchmarks.Incremental_EditQueryFile_E2E(CallSiteCount: 1) 173105.66446358818 ns (± 4964.051425441417) 103181.56585467303 ns (± 1443.1701224146884) 1.68
ExpressiveSharp.Benchmarks.GeneratorBenchmarks.RunGenerator_Incremental_NoiseChange(ExpressiveCount: 1) 122455.33451334636 ns (± 11051.533988681776) 36285.74476044754 ns (± 142.57008342554704) 3.37
ExpressiveSharp.Benchmarks.GeneratorBenchmarks.RunGenerator_Incremental_ExpressiveChange(ExpressiveCount: 1) 368581.20061383926 ns (± 63419.807805559416) 231644.02336516205 ns (± 2882.149803059769) 1.59
ExpressiveSharp.Benchmarks.PolyfillMultiFileBenchmarks.Incremental_EditNoiseFile(FileCount: 1) 26603.36689213344 ns (± 577.8697159206029) 13117.91486911116 ns (± 234.49681495253603) 2.03
ExpressiveSharp.Benchmarks.PolyfillMultiFileBenchmarks.Cold_E2E(FileCount: 1) 706905.8900188578 ns (± 147492.96660782362) 413853.1696777344 ns (± 2270.5321442797767) 1.71
ExpressiveSharp.Benchmarks.PolyfillMultiFileBenchmarks.Incremental_EditCallSiteFile_E2E(FileCount: 1) 826032.0563802083 ns (± 93906.7561095551) 415329.6954571759 ns (± 3250.9386882382933) 1.99
ExpressiveSharp.Benchmarks.PolyfillMultiFileBenchmarks.Incremental_EditNoiseFile_E2E(FileCount: 1) 34733.378897603354 ns (± 4061.60730580264) 12966.112665303548 ns (± 52.384123646896576) 2.68
ExpressiveSharp.Benchmarks.PolyfillMultiFileBenchmarks.Incremental_EditCallSiteFile(FileCount: 5) 643406.8684430803 ns (± 6394.438197319165) 422995.8761449353 ns (± 1747.17707701696) 1.52
ExpressiveSharp.Benchmarks.PolyfillMultiFileBenchmarks.Incremental_EditNoiseFile(FileCount: 5) 40156.58067016602 ns (± 1188.3226838822527) 22306.184678254303 ns (± 71.1545242083992) 1.80
ExpressiveSharp.Benchmarks.PolyfillMultiFileBenchmarks.Incremental_EditCallSiteFile_E2E(FileCount: 5) 634804.8120442708 ns (± 4959.961482713524) 415863.7177734375 ns (± 2812.5709133438013) 1.53
ExpressiveSharp.Benchmarks.PolyfillMultiFileBenchmarks.Incremental_EditNoiseFile_E2E(FileCount: 5) 37324.68146623884 ns (± 271.95369172134156) 21892.42452457973 ns (± 155.45512774272223) 1.70
ExpressiveSharp.Benchmarks.PolyfillSingleFileBenchmarks.Incremental_EditEntityFile(CallSiteCount: 10) 26563.896352914664 ns (± 153.96148571052146) 11988.17700246175 ns (± 228.13656136971179) 2.22
ExpressiveSharp.Benchmarks.PolyfillSingleFileBenchmarks.Cold_E2E(CallSiteCount: 10) 1184002.6624710648 ns (± 10571.410538491753) 784331.8501481682 ns (± 2499.001462297786) 1.51
ExpressiveSharp.Benchmarks.PolyfillSingleFileBenchmarks.Incremental_EditEntityFile_E2E(CallSiteCount: 10) 26307.906501506935 ns (± 509.81971219116355) 12138.207806291251 ns (± 180.12314175021876) 2.17
ExpressiveSharp.Benchmarks.PolyfillSingleFileBenchmarks.Incremental_EditQueryFile_E2E(CallSiteCount: 10) 1236359.7493024555 ns (± 91545.62715835706) 780107.4015764509 ns (± 5053.253076700255) 1.58
ExpressiveSharp.Benchmarks.PolyfillMultiFileBenchmarks.Incremental_EditNoiseFile(FileCount: 10) 55443.54684343009 ns (± 5513.092607464485) 33333.12653459822 ns (± 506.4422538032499) 1.66
ExpressiveSharp.Benchmarks.PolyfillMultiFileBenchmarks.Cold_E2E(FileCount: 10) 5998703.013950893 ns (± 744614.2225140822) 3861006.6311383927 ns (± 30840.296837610746) 1.55
ExpressiveSharp.Benchmarks.PolyfillMultiFileBenchmarks.Incremental_EditCallSiteFile_E2E(FileCount: 10) 750328.2985026041 ns (± 47647.13126884926) 439912.0978009259 ns (± 1861.0306795804056) 1.71
ExpressiveSharp.Benchmarks.PolyfillMultiFileBenchmarks.Incremental_EditNoiseFile_E2E(FileCount: 10) 55597.877081977 ns (± 1176.114481334618) 33373.23373518319 ns (± 289.6154008265203) 1.67
ExpressiveSharp.Benchmarks.PolyfillColdBuildWithNoiseBenchmarks.Cold_E2E(NoiseInvocationsPerFile: 25) 12127431.199074075 ns (± 4962339.428827582) 5295465.934430803 ns (± 25361.183794887158) 2.29
ExpressiveSharp.Benchmarks.PolyfillColdBuildWithNoiseBenchmarks.Incremental_EditCallSiteFile_E2E(NoiseInvocationsPerFile: 25) 1416713.6340494792 ns (± 375080.77413609327) 613472.2170662716 ns (± 15110.756345109065) 2.31
ExpressiveSharp.Benchmarks.PolyfillSingleFileBenchmarks.Incremental_EditEntityFile(CallSiteCount: 100) 23798.208272298176 ns (± 626.1636039683046) 12009.999867932549 ns (± 174.32245097439858) 1.98
ExpressiveSharp.Benchmarks.PolyfillSingleFileBenchmarks.Incremental_EditEntityFile_E2E(CallSiteCount: 100) 49082.81188754378 ns (± 8689.387045182972) 12419.224816385906 ns (± 120.12755235648945) 3.95
ExpressiveSharp.Benchmarks.PolyfillSingleFileBenchmarks.Incremental_EditQueryFile_E2E(CallSiteCount: 100) 16219914.839439655 ns (± 5122245.4129088055) 7590177.487239583 ns (± 110757.41563184577) 2.14
ExpressiveSharp.Benchmarks.GeneratorBenchmarks.RunGenerator_Incremental_NoiseChange(ExpressiveCount: 100) 917171.0166341146 ns (± 265595.6272269421) 446871.6522135417 ns (± 2407.1209064308377) 2.05
ExpressiveSharp.Benchmarks.GeneratorBenchmarks.RunGenerator_Incremental_ExpressiveChange(ExpressiveCount: 100) 5077928.016927083 ns (± 1108279.5246167376) 3274847.9932291666 ns (± 216901.46442576713) 1.55
ExpressiveSharp.Benchmarks.PolyfillColdBuildWithNoiseBenchmarks.Cold(NoiseInvocationsPerFile: 100) 16438071.116145832 ns (± 3281338.052294892) 6148593.61077009 ns (± 29755.15166927911) 2.67
ExpressiveSharp.Benchmarks.PolyfillColdBuildWithNoiseBenchmarks.Incremental_EditCallSiteFile(NoiseInvocationsPerFile: 100) 1567166.8798177084 ns (± 356305.9176085337) 936651.0927083333 ns (± 106940.12467770673) 1.67
ExpressiveSharp.Benchmarks.GeneratorBenchmarks.RunGenerator_Incremental_ExpressiveChange(ExpressiveCount: 1000) 23724070.7125 ns (± 7580631.763055796) 10983708.229525862 ns (± 157544.50778013677) 2.16

This comment was automatically generated by workflow using github-action-benchmark.

@koenbeuk koenbeuk merged commit 07cde84 into main Apr 27, 2026
20 checks passed
@koenbeuk koenbeuk deleted the feat/expressive-for-synthesize branch April 27, 2026 01:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Suggestion] Non-nullable value type projectable verbosity

2 participants